package com.tjbklx1.redis.chap02;

import java.util.ArrayList;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import redis.clients.jedis.Jedis;

/**
 * 购物车
 * @date 2018年9月7日
 */
public class App22 {

	public static void main(String[] args) throws InterruptedException {
		Jedis conn = new Jedis("localhost");
		conn.select(0);
		new App22().testShopppingCartCookies(conn);
	}

	private void testShopppingCartCookies(Jedis conn) throws InterruptedException {
		System.out.println("\n----- testShopppingCartCookies -----");
		String token = UUID.randomUUID().toString();

		System.out.println("We'll refresh our session...");
		updateToken(conn, token, "username", "itemX");
		System.out.println("And add an item to the shopping cart");
		addToCart(conn, token, "itemY", 3);
		//查询购物车
		Map<String, String> r = conn.hgetAll("cart:" + token);
		System.out.println("Our shopping cart currently has:");
		for (Map.Entry<String, String> entry : r.entrySet()) {
			System.out.println("  " + entry.getKey() + ": " + entry.getValue());
		}
		System.out.println();

		assert r.size() >= 1;

		System.out.println("Let's clean out our sessions and carts");
		CleanFullSessionsThread thread = new CleanFullSessionsThread(0);
		thread.start();
		Thread.sleep(1000);
		thread.quit();
		Thread.sleep(2000);
		if (thread.isAlive()) {
			throw new RuntimeException("The clean sessions thread is still alive?!?");
		}

		//查询购物车
		r = conn.hgetAll("cart:" + token);
		System.out.println("Our shopping cart now contains:");
		for (Map.Entry<String, String> entry : r.entrySet()) {
			System.out.println("  " + entry.getKey() + ": " + entry.getValue());
		}
		assert r.size() == 0;
	}

	public void updateToken(Jedis conn, String token, String user, String item) {
		long timestamp = System.currentTimeMillis() / 1000;
		//hash
		conn.hset("login:", token, user);
		//zset 
		conn.zadd("recent:", timestamp, token);
		if (item != null) {
			//浏览的商品 zset
			conn.zadd("viewed:" + token, timestamp, item);
			//删除大于25的商品
			conn.zremrangeByRank("viewed:" + token, 0, -26);
			//修改计数器
			conn.zincrby("viewed:", -1, item);
		}
	}

	/**
	 * 加入购物车
	 * @param conn
	 * @param session token
	 * @param item 商品ID
	 * @param count 数量
	 * @date 2018年9月7日
	 */
	public void addToCart(Jedis conn, String session, String item, int count) {
		if (count <= 0) {
			conn.hdel("cart:" + session, item);
		} else {
			conn.hset("cart:" + session, item, String.valueOf(count));
		}
	}

	public class CleanFullSessionsThread extends Thread {
		private Jedis conn;
		private int limit;
		private boolean quit;

		public CleanFullSessionsThread(int limit) {
			this.conn = new Jedis("localhost");
			this.conn.select(0);
			this.limit = limit;
		}

		public void quit() {
			quit = true;
		}

		public void run() {
			while (!quit) {
				long size = conn.zcard("recent:");
				if (size <= limit) {
					try {
						sleep(1000);
					} catch (InterruptedException ie) {
						Thread.currentThread().interrupt();
					}
					continue;
				}

				//大于限制的数量 要清理
				long endIndex = Math.min(size - limit, 100);
				Set<String> sessionSet = conn.zrange("recent:", 0, endIndex - 1);
				String[] sessions = sessionSet.toArray(new String[sessionSet.size()]);

				ArrayList<String> sessionKeys = new ArrayList<String>();
				for (String sess : sessions) {
					sessionKeys.add("viewed:" + sess);
					sessionKeys.add("cart:" + sess);
				}

				conn.del(sessionKeys.toArray(new String[sessionKeys.size()])); //清理token
				conn.hdel("login:", sessions);//清理登录
				conn.zrem("recent:", sessions);//清理浏览的商品
			}
		}
	}
}
